using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Text;
using jcs.Core;
using jcs.Core.Data;
using jcs.Core.SSManager;
using jcs.Ifc.SSManager;

namespace jcs.Dat.SSManager
{
    public static class SnapshotProvider
    {
        public static List<ISnapshot> GetExistingSnapshots(string snapShotExtension)
        {
            List<ISnapshot> returnValue = null;
            IDataReader rdr = null;

            try
            {
                string query = String.Format(DBObjects.Default.GetExistingSnapshots, snapShotExtension);
                if (query == string.Empty)
                {
                    return null;
                }

                List<string> logicalNames = GetLogicalFileNames();

                rdr = DataProvider.GetDataReader(query);

                if (rdr == null)
                {
                    return null;
                }
                while (rdr.Read())
                {
                    if (returnValue == null)
                    {
                        returnValue = new List<ISnapshot>();
                    }

                    ISnapshot snap = Factory.GetSnapshot(rdr.GetString(0), logicalNames[0], rdr.GetString(2),
                                                         snapShotExtension, rdr.GetDateTime(1));
                    if (snap != null)
                    {
                        returnValue.Add(snap);
                    }
                }
            }
            finally
            {
                DataProvider.SwatFlyWithBuick(ref rdr);
            }

            return returnValue;
        }

        //todo:  write a test
        public static List<string> GetLogicalFileNames()
        {
            List<string> returnValue = null;
            IDataReader rdr = null;

            try
            {
                string query = DBObjects.Default.GetLogicalFileNames;
                if (query == string.Empty)
                {
                    return null;
                }
                rdr = DataProvider.GetDataReader(query);
                while (rdr.Read())
                {
                    if (returnValue == null)
                    {
                        returnValue = new List<string>();
                    }
                    string val = DataProvider.GetReaderItem(rdr, 0, string.Empty);
                    returnValue.Add(val);
                }
            }
            finally
            {
                DataProvider.SwatFlyWithBuick(ref rdr);
            }

            return returnValue;
        }

        public static Boolean CreateSnapshot(ISnapshot snapShot)
        {
            if (StringProvider.StringIsOfLength(0, snapShot.SnapshotName,
                                                snapShot.LogicalFileName, snapShot.FilePath))
            {
                return false;
            }

            DbCommand cmd = null;

            try
            {
                List<string> names = GetLogicalFileNames();

                var builder = new StringBuilder();
                builder.Append(String.Format("CREATE DATABASE {0} ON", snapShot.SnapshotName));

                for (int i = 0; i <= (names.Count - 1); i++)
                {
                    string fullFilePath = String.Concat(snapShot.FilePath, snapShot.SnapshotName, i.ToString(), ".snap");
                    if (File.Exists(fullFilePath)) File.Delete(fullFilePath);
                    builder.Append(string.Format(" (NAME = {0}, FILENAME = '{1}') ", names[i], fullFilePath));
                    if (i != (names.Count - 1)) builder.Append(", ");
                }

                builder.Append(" AS SNAPSHOT OF SnapshotTestDatabase;");

                cmd = DataProvider.GetCommand(string.Empty, builder.ToString(),
                                              DataProvider.EntlibDataCommandType.SqlString, false);
                cmd.Connection.Open();
                cmd.ExecuteNonQuery();
                cmd.Connection.Close();
            }
            finally
            {
                DataProvider.SwatFlyWithBuick(ref cmd);
            }

            return true;
        }

        private static string GetUniqueFullPathOfNewSnapshot(ISnapshot snapShot)
        {
            DateTime currentDt = DateTime.Now;
            string identifier = String.Concat(currentDt.Month.ToString(), currentDt.Day.ToString(),
                                              currentDt.Year.ToString(),
                                              currentDt.Hour.ToString(), currentDt.Minute.ToString(),
                                              currentDt.Second.ToString(),
                                              currentDt.Millisecond.ToString());
            return String.Concat(snapShot.FilePath, snapShot.SnapshotName, identifier);
        }

        public static Boolean DeleteSnapshots(List<string> names, string extension)
        {

            if (StringProvider.StringIsOfLength(0, names.ToArray()))
            {
                return false;
            }

            var scrubbedNames = new List<string>();

            names.ForEach(name => scrubbedNames.Add(ScrubSnapshotNames(name, extension)));

            DbCommand cmd = null;

            try
            {
                var queryBuilder = new StringBuilder();
                scrubbedNames.ForEach(name => queryBuilder.Append(String.Format(DBObjects.Default.DeleteSnapshot, name)));
                cmd = DataProvider.GetCommand(string.Empty, queryBuilder.ToString(),
                                              DataProvider.EntlibDataCommandType.SqlString, false);
                cmd.Connection.Open();
                cmd.ExecuteNonQuery();
                cmd.Connection.Close();
            }
            finally
            {
                DataProvider.SwatFlyWithBuick(ref cmd);
            }

            return true;
        }

        private static string ScrubSnapshotNames(string name, string extention)
        {
            if (name.EndsWith(extention))
            {
                return name;
            }
            return String.Concat(name, extention);
        }
    }
}